package com.w.waiagent.config;

import cn.hutool.json.JSONUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * 自定义 TypeHandler 用于处理 List<String> 和数据库中逗号分隔字符串之间的转换。
 */
@MappedTypes(List.class) // 指定此处理器能够处理的 Java 类型
public class StringListTypeHandler extends BaseTypeHandler<List<String>> {

    /**
     * 定义列表项之间的分隔符，默认为逗号。
     */
    private static final String DELIMITER = ",";

    /**
     * 将 List<String> 转换为逗号分隔的字符串，并设置到 PreparedStatement 中。
     *
     * @param ps        PreparedStatement 对象，用于执行 SQL 查询
     * @param i         参数索引位置
     * @param parameter 需要转换并设置的参数值
     * @param jdbcType  JDBC 类型（通常为 VARCHAR）
     * @throws SQLException 如果发生 SQL 错误
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        // 使用指定的分隔符连接列表中的元素，并作为字符串设置到 PreparedStatement 中
        ps.setString(i, String.join(DELIMITER, parameter));
    }

    /**
     * 从 ResultSet 中获取结果，并将其解析为 List<String>。
     *
     * @param rs         ResultSet 对象，包含查询结果
     * @param columnName 列名，用于定位特定列的数据
     * @return 解析后的 List<String>
     * @throws SQLException 如果发生 SQL 错误
     */
    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return parseStringToList(rs.getString(columnName)); // 获取并解析字符串为列表
    }

    /**
     * 从 ResultSet 中根据列索引获取结果，并将其解析为 List<String>。
     *
     * @param rs          ResultSet 对象，包含查询结果
     * @param columnIndex 列索引，用于定位特定列的数据
     * @return 解析后的 List<String>
     * @throws SQLException 如果发生 SQL 错误
     */
    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return parseStringToList(rs.getString(columnIndex)); // 获取并解析字符串为列表
    }

    /**
     * 从 CallableStatement 中获取结果，并将其解析为 List<String>。
     *
     * @param cs          CallableStatement 对象，用于执行存储过程
     * @param columnIndex 列索引，用于定位特定列的数据
     * @return 解析后的 List<String>
     * @throws SQLException 如果发生 SQL 错误
     */
    @Override
    public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return parseStringToList(cs.getString(columnIndex)); // 获取并解析字符串为列表
    }

    /**
     * 将逗号分隔的字符串解析为 List<String>。
     *
     * @param str 字符串形式的列表数据
     * @return 解析后的 List<String>
     */
    private List<String> parseStringToList(String str) {
        if (str == null || str.isEmpty()) {
            return null; // 如果输入为空或空字符串，则返回 null
        }
        // 字符串 转 List<String>
        return JSONUtil.toList(str, String.class);
    }
}